%%%-------------------------------------------------------------------
%%% @author wukai
%%% @copyright (C) 2017, <COMPANY>
%%% @doc
%%%
%%% @end
%%% Created : 20. 十二月 2017 20:18
%%%-------------------------------------------------------------------
-module(cache_server).
-author("wukai").

-behaviour(gen_server).
-record(cache_publish, {
  client,
  msg,
  time
}).
-define(CACHE_TABLE, cache_publish).
%% API
-export([start_link/0]).
-export([send_send/2]).
-export([send_save/2]).
-export([cre_tab/0]).

-export([init/1,
  handle_call/3,
  handle_cast/2,
  handle_info/2,
  terminate/2,
  code_change/3]).

-define(SERVER, ?MODULE).

-record(state, {}).

start_link() ->
  gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).

init([]) ->
  {ok, #state{}}.
handle_call(_Request, _From, State) ->
  {reply, ok, State}.
handle_cast({save,Client,MsgList}, State) ->
  save(Client,MsgList),
  {noreply, State};
handle_cast({send,Client,To}, State) ->
  send(Client,To),
  {noreply, State};
handle_cast(_Request, State) ->
  {noreply, State}.
handle_info(_Info, State) ->
  {noreply, State}.

terminate(_Reason, _State) ->
  ok.

code_change(_OldVsn, State, _Extra) ->
  {ok, State}.


send(Client,To) ->
  F = fun() -> mnesia:read({?CACHE_TABLE, Client}) end,
  case mnesia:transaction(F) of
    {atomic, ResultOfFun} ->
      List = lists:foldl(fun(E, X) -> X ++ [E#cache_publish.msg] end, [], ResultOfFun),
      if
        length(List) >= 1 ->
          lists:foreach(fun(Msg) -> mqtt_process:send_msg(To, Msg) end, List),
          mnesia:transaction(fun() -> mnesia:delete({?CACHE_TABLE, Client}) end),
          List;
        true -> ok
      end;
    {abort, Reason} -> log:log("look retian msg error ~p", [Reason]), error
  end.

%%创建表
cre_tab() ->
  mnesia:create_table(?CACHE_TABLE,
    [
      {storage_properties, [{dets, [{auto_save, 3000}]}]},
      {disc_copies, [node() | nodes()]},
      {type, bag},
      {attributes, record_info(fields, cache_publish)}
    ]
  ).

%%批量写入
save(Client, MsgList) ->
  log:log("save cache_publish ~p",[MsgList]),
  T = time_utils:timestamp(),
  Items = [#cache_publish{client = Client, time = T, msg = M} || M <- MsgList],
  F = fun()->lists:foreach(fun(Item) -> mnesia:write(Item) end, Items) end,
  case mnesia:transaction(F) of
    {atomic, Val} ->
      io:format("write noack success ~n"),
      {Val};
    {aborted, Reason} ->
      io:format("write noack error ~p", [Reason]);
    Other->log:log("write noack error ~p", [Other])
  end.

send_save(Client,MsgList)->
  gen_server:cast(cache_server,{save,Client,MsgList}).
send_send(Client,To)->
  gen_server:cast(cache_server,{send,Client,To}).